home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume15 / dis88 / part01 next >
Encoding:
Internet Message Format  |  1988-05-23  |  48.9 KB

  1. Subject:  v15i006:  Symbolic disassembler for PC/IX, Part01/02
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: "G. M. Harding" <gm@uts.amdahl.com>
  7. Posting-number: Volume 15, Issue 6
  8. Archive-name: dis88/part01
  9.  
  10. [  I packed up the archives and turned the formatted manpage
  11.    into an unformatted one.  --r$  ]
  12.  
  13.      "Dis88" is a symbolic disassembler for the Intel 8088 CPU,
  14.     designed to run under the PC/IX  operating  system on an IBM XT
  15.     or fully-compatible clone.  Its output is in the format of, and
  16.     is completely compatible with, the PC/IX assembler,  "as".  The
  17.     program is copyrighted by its author, but may be copied and re-
  18.     distributed freely provided that complete source code, with all
  19.     copyright notices, accompanies any distribution. This provision
  20.     also applies to any  modifications you may make.  You are urged
  21.     to comment such changes,  giving,  as a miminum,  your name and
  22.     complete address.
  23.  
  24.     ---
  25.     G. M. HARDING
  26.     POB 4142
  27.     Santa Clara CA  95054-0142
  28.  
  29. #! /bin/sh
  30. # This is a shell archive.  Remove anything before this line, then unpack
  31. # it by saving it into a file and typing "sh file".  To overwrite existing
  32. # files, type "sh file -c".  You can also feed this as standard input via
  33. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  34. # will see the following message at the end:
  35. #        "End of archive 1 (of 2)."
  36. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  37. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  38.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  39. else
  40. echo shar: Extracting \"'MANIFEST'\" \(406 characters\)
  41. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  42. X   File Name        Archive #    Description
  43. X-----------------------------------------------------------
  44. X MANIFEST                   1    
  45. X Makefile                   1    
  46. X README                     1    
  47. X dis.h                      1    
  48. X dis88.1                    1    
  49. X disfp.c                    1    
  50. X dishand.c                  2    
  51. X dismain.c                  1    
  52. X disrel.c                   1    
  53. X distabs.c                  2    
  54. END_OF_FILE
  55. if test 406 -ne `wc -c <'MANIFEST'`; then
  56.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  57. fi
  58. # end of 'MANIFEST'
  59. fi
  60. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  61.   echo shar: Will not clobber existing file \"'Makefile'\"
  62. else
  63. echo shar: Extracting \"'Makefile'\" \(1593 characters\)
  64. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  65. X# @(#) Makefile, Ver. 2.1 created 00:00:00 87/09/01
  66. X# Makefile for 8088 symbolic disassembler
  67. X
  68. X# Copyright (C) 1987 G. M. Harding, all rights reserved.
  69. X# Permission to copy and redistribute is hereby granted,
  70. X# provided full source code, with all copyright notices,
  71. X# accompanies any redistribution.
  72. X
  73. X# This Makefile  automates the process of compiling and linking
  74. X# a symbolic  object-file  disassembler  program  for the Intel
  75. X# 8088 CPU. Relatively machine-independent code is contained in
  76. X# the file dismain.c; lookup tables and handler routines, which
  77. X# are by their nature  machine-specific,  are  contained in two
  78. X# files named distabs.c and dishand.c,  respectively.  (A third
  79. X# machine-specific file, disfp.c, contains handler routines for
  80. X# floating-point  coprocessor opcodes.)  A header file,  dis.h,
  81. X# attempts to mediate between the machine-specific and machine-
  82. X# independent portions of the code. An attempt has been made to
  83. X# isolate machine  dependencies and to deal with them in fairly
  84. X# straightforward ways. Thus, it should be possible to target a
  85. X# different CPU by rewriting the handler  routines and changing
  86. X# the initialization  data in the lookup tables.  It should not
  87. X# be necessary to alter the formats of the tables.
  88. X
  89. OBJ = disrel.o dismain.o distabs.o dishand.o disfp.o
  90. X
  91. dis88 : $(OBJ)
  92. X    ld -i -s -o dis88 /lib/crt0.o $(OBJ) -lc
  93. X    size dis88
  94. X    @echo "\07Build of 'dis88' complete." > /dev/tty
  95. X
  96. X.c.o :
  97. X    cc -O -c $<
  98. X    chmod 600 $*.o
  99. X
  100. disrel.o : disrel.c
  101. X
  102. dismain.o : dismain.c dis.h
  103. X
  104. distabs.o : distabs.c dis.h
  105. X
  106. dishand.o : dishand.c dis.h
  107. X
  108. disfp.o : disfp.c dis.h
  109. X
  110. END_OF_FILE
  111. if test 1593 -ne `wc -c <'Makefile'`; then
  112.     echo shar: \"'Makefile'\" unpacked with wrong size!
  113. fi
  114. # end of 'Makefile'
  115. fi
  116. if test -f 'README' -a "${1}" != "-c" ; then 
  117.   echo shar: Will not clobber existing file \"'README'\"
  118. else
  119. echo shar: Extracting \"'README'\" \(4898 characters\)
  120. sed "s/^X//" >'README' <<'END_OF_FILE'
  121. X                                     dis88
  122. X                                  Beta Release
  123. X                                    87/09/01
  124. X                                      ---
  125. X                                 G. M. HARDING
  126. X                                    POB 4142
  127. X                           Santa Clara CA  95054-0142
  128. X
  129. X
  130. X             "Dis88" is a symbolic disassembler for the Intel 8088 CPU,
  131. X        designed to run under the PC/IX  operating  system on an IBM XT
  132. X        or fully-compatible clone.  Its output is in the format of, and
  133. X        is completely compatible with, the PC/IX assembler,  "as".  The
  134. X        program is copyrighted by its author, but may be copied and re-
  135. X        distributed freely provided that complete source code, with all
  136. X        copyright notices, accompanies any distribution. This provision
  137. X        also applies to any  modifications you may make.  You are urged
  138. X        to comment such changes,  giving,  as a miminum,  your name and
  139. X        complete address.
  140. X
  141. X             This release of the program is a beta release, which means
  142. X        that it has been  extensively,  but not  exhaustively,  tested.
  143. X        User comments, recommendations, and bug fixes are welcome.  The
  144. X        principal features of the current release are:
  145. X
  146. X             (a)  The ability to  disassemble  any file in PC/IX object
  147. X        format, making full use of symbol and relocation information if
  148. X        it is present,  regardless of whether the file is executable or
  149. X        linkable,  and regardless of whether it has continuous or split
  150. X        I/D space;
  151. X
  152. X             (b)  Automatic generation of synthetic labels when no sym-
  153. X        bol table is available; and
  154. X
  155. X             (c)  Optional  output of address and object-code  informa-
  156. X        tion as assembler comment text.
  157. X
  158. X             Limitations of the current release are:
  159. X
  160. X             (a)  Numeric co-processor  (i.e., 8087)  mnemonics are not
  161. X        supported.  Instructions  for the co-processor are disassembled
  162. X        as CPU escape  sequences,  or as  interrupts,  depending on how
  163. X        they were assembled in the first place. This limitation will be
  164. X        addressed in a future release.
  165. X
  166. X             (b)  Symbolic  references  within the object  file's  data
  167. X        segment are not supported. Thus, for example, if a data segment
  168. X        location is initialized to point to a text segment address,  no
  169. X        reference to a text segment symbol will be detected. This limi-
  170. X        tation is likely to remain in future  releases,  because object
  171. X        code does not, in most cases, contain sufficient information to
  172. X        allow meaningful interpretation of pure data.  (Note,  however,
  173. X        that  symbolic  references  to the data segment from within the
  174. X        text segment are always supported.)
  175. X
  176. X             As a final caveat,  be aware that the PC/IX assembler does
  177. X        not recognize the  "esc"  mnemonic,  even though it refers to a
  178. X        completely  valid CPU operation  which is documented in all the
  179. X        Intel literature. Thus, the corresponding opcodes (0xd8 through
  180. X        0xdf) are disassembled as .byte directives. For reference, how-
  181. X        ever,  the syntactically-correct "esc" instruction is output as
  182. X        a comment.
  183. X
  184. X             To build the disassembler program, transfer all the source
  185. X        files,  together with the Makefile,  to a suitable  (preferably
  186. X        empty) PC/IX directory. Then, simply type "make".
  187. X
  188. X             To use dis88,  place it in a  directory  which  appears in
  189. X        your $PATH list.  It may then be invoked by name from  whatever
  190. X        directory you happen to be in.  As a minimum,  the program must
  191. X        be invoked with one command-line argument:  the name of the ob-
  192. X        ject file to be disassembled.  (Dis88 will complain if the file
  193. X        specified is not an object file.)  Optionally,  you may specify
  194. X        an output file; stdout is the default.  One command-line switch
  195. X        is available:  "-o",  which makes the program display addresses
  196. X        and object code along with its mnemonic disassembly.
  197. X
  198. X             The "-o" option is useful primarily for verifying the cor-
  199. X        rectness of the program's output. In particular, it may be used
  200. X        to check the accuracy of local  relative  jump  opcodes.  These
  201. X        jumps often  target  local  labels,  which are lost at assembly
  202. X        time;  thus,  the disassembly may contain cryptic  instructions
  203. X        like "jnz .+39".  As a user convenience,  all relative jump and
  204. X        call  opcodes are output with a comment  which  identifies  the
  205. X        physical target address.
  206. X
  207. X             By convention, the release level of the program as a whole
  208. X        is the SID of the file disrel.c, and this SID string appears in
  209. X        each disassembly.  Release 2.1 of the program is the first beta
  210. X        release to be distributed on Usenet.
  211. X
  212. END_OF_FILE
  213. if test 4898 -ne `wc -c <'README'`; then
  214.     echo shar: \"'README'\" unpacked with wrong size!
  215. fi
  216. # end of 'README'
  217. fi
  218. if test -f 'dis.h' -a "${1}" != "-c" ; then 
  219.   echo shar: Will not clobber existing file \"'dis.h'\"
  220. else
  221. echo shar: Extracting \"'dis.h'\" \(7563 characters\)
  222. sed "s/^X//" >'dis.h' <<'END_OF_FILE'
  223. X /*
  224. X ** @(#) dis.h, Ver. 2.1 created 00:00:00 87/09/01
  225. X */
  226. X
  227. X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  228. X  *                                                         *
  229. X  *  Copyright (C) 1987 G. M. Harding, all rights reserved  *
  230. X  *                                                         *
  231. X  * Permission to copy and  redistribute is hereby granted, *
  232. X  * provided full source code,  with all copyright notices, *
  233. X  * accompanies any redistribution.                         *
  234. X  *                                                         *
  235. X  * This file contains declarations and definitions used by *
  236. X  * the 8088 disassembler program. The program was designed *
  237. X  * for execution on a machine of its own type (i.e., it is *
  238. X  * not designed as a cross-disassembler);  consequently, A *
  239. X  * SIXTEEN-BIT INTEGER SIZE HAS BEEN ASSUMED. This assump- *
  240. X  * tion is not particularly important,  however, except in *
  241. X  * the machine-specific  portions of the code  (i.e.,  the *
  242. X  * handler  routines and the optab[] array).  It should be *
  243. X  * possible to override this assumption,  for execution on *
  244. X  * 32-bit machines,  by use of a  pre-processor  directive *
  245. X  * (see below); however, this has not been tested.         *
  246. X  *                                                         *
  247. X  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  248. X
  249. X#include <stdio.h>      /* System standard I/O definitions  */
  250. X#include <fcntl.h>      /* System file-control definitions  */
  251. X#include <a.out.h>      /* Object file format definitions   */
  252. X
  253. X#if i8086 || i8088      /* For CPU's with 16-bit integers   */
  254. X#undef int
  255. X#else                   /* Defaults (for 32-bit CPU types)  */
  256. X#define int short
  257. X#endif
  258. X
  259. X#define MAXSYM 1500     /* Maximum entries in symbol table  */
  260. X
  261. extern struct nlist     /* Array to hold the symbol table   */
  262. X   symtab[MAXSYM];
  263. X
  264. extern struct reloc     /* Array to hold relocation table   */
  265. X   relo[MAXSYM];
  266. X
  267. extern int symptr;      /* Index into the symtab[] array    */
  268. X
  269. extern int relptr;      /* Index into the relo[] array      */
  270. X
  271. struct opcode           /* Format for opcode data records   */
  272. X   {
  273. X   char     *text;            /* Pointer to mnemonic text   */
  274. X   void     (*func)();        /* Pointer to handler routine */
  275. X   unsigned min;              /* Minimum # of object bytes  */
  276. X   unsigned max;              /* Maximum # of object bytes  */
  277. X   };
  278. X
  279. extern struct opcode    /* Array to hold the opcode table   */
  280. X  optab[256];
  281. X
  282. X /*
  283. X   +---------------------------------------------
  284. X   | The following  functions are the specialized
  285. X   | handlers for each opcode group. They are, of
  286. X   | course, highly MACHINE-SPECIFIC.  Each entry
  287. X   | in the opcode[]  array contains a pointer to
  288. X   | one of these  handlers.  The handlers in the
  289. X   | first group are in  dishand.c;  those in the
  290. X   | second group are in disfp.c.
  291. X   +---------------------------------------------
  292. X */
  293. X
  294. extern void dfhand(),   /* Default handler routine          */
  295. X            sbhand(),   /* Single-byte handler              */
  296. X            aohand(),   /* Arithmetic-op handler            */
  297. X            sjhand(),   /* Short-jump handler               */
  298. X            imhand(),   /* Immediate-operand handler        */
  299. X            mvhand(),   /* Simple move handler              */
  300. X            mshand(),   /* Segreg-move handler              */
  301. X            pohand(),   /* Pop memory/reg handler           */
  302. X            cihand(),   /* Intersegment call handler        */
  303. X            mihand(),   /* Immediate-move handler           */
  304. X            mqhand(),   /* Quick-move handler               */
  305. X            tqhand(),   /* Quick-test handler               */
  306. X            rehand(),   /* Return handler                   */
  307. X            mmhand(),   /* Move-to-memory handler           */
  308. X            srhand(),   /* Shift and rotate handler         */
  309. X            aahand(),   /* ASCII-adjust handler             */
  310. X            iohand(),   /* Immediate port I/O handler       */
  311. X            ljhand(),   /* Long-jump handler                */
  312. X            mahand(),   /* Misc. arithmetic handler         */
  313. X            mjhand();   /* Miscellaneous jump handler       */
  314. X
  315. extern void eshand(),   /* Bus-escape opcode handler        */
  316. X            fphand(),   /* Floating-point handler           */
  317. X            inhand();   /* Interrupt-opcode handler         */
  318. X
  319. extern char *REGS[];    /* Table of register names          */
  320. X
  321. extern char *REGS0[];   /* Mode 0 register name table       */
  322. X
  323. extern char *REGS1[];   /* Mode 1 register name table       */
  324. X
  325. X#define AL REGS[0]      /* CPU register manifests           */
  326. X#define CL REGS[1]
  327. X#define DL REGS[2]
  328. X#define BL REGS[3]
  329. X#define AH REGS[4]
  330. X#define CH REGS[5]
  331. X#define DH REGS[6]
  332. X#define BH REGS[7]
  333. X#define AX REGS[8]
  334. X#define CX REGS[9]
  335. X#define DX REGS[10]
  336. X#define BX REGS[11]
  337. X#define SP REGS[12]
  338. X#define BP REGS[13]
  339. X#define SI REGS[14]
  340. X#define DI REGS[15]
  341. X#define ES REGS[16]
  342. X#define CS REGS[17]
  343. X#define SS REGS[18]
  344. X#define DS REGS[19]
  345. X#define BX_SI REGS0[0]
  346. X#define BX_DI REGS0[1]
  347. X#define BP_SI REGS0[2]
  348. X#define BP_DI REGS0[3]
  349. X
  350. extern int symrank[6][6];     /* Symbol type/rank matrix    */
  351. X
  352. extern unsigned long PC;      /* Current program counter    */
  353. X
  354. extern int segflg;      /* Flag: segment override in effect */
  355. X
  356. extern int objflg;      /* Flag: output object as a comment */
  357. X
  358. X#define OBJMAX 8        /* Size of the object code buffer   */
  359. X
  360. extern unsigned char    /* Internal buffer for object code  */
  361. X   objbuf[OBJMAX];
  362. X
  363. extern void objini(),   /* Object-buffer init routine       */
  364. X            objout();   /* Object-code output routine       */
  365. X
  366. extern int objptr;      /* Index into the objbuf[] array    */
  367. X
  368. extern void badseq();   /* Bad-code-sequence function       */
  369. X
  370. extern char *getnam();  /* Symbol-name string function      */
  371. X
  372. extern char *lookup();  /* Symbol-table lookup function     */
  373. X
  374. extern int lookext();   /* Extern-definition lookup routine */
  375. X
  376. extern char *mtrans();  /* Interpreter for the mode byte    */
  377. X
  378. extern void mtrunc();   /* Mode string truncator function   */
  379. X
  380. extern char ADD[],      /* Opcode family mnemonic strings   */
  381. X            OR[],
  382. X            ADC[],
  383. X            SBB[],
  384. X            AND[],
  385. X            SUB[],
  386. X            XOR[],
  387. X            CMP[],
  388. X            NOT[],
  389. X            NEG[],
  390. X            MUL[],
  391. X            DIV[],
  392. X            MOV[],
  393. X            ESC[],
  394. X            TEST[],
  395. X            AMBIG[];
  396. X
  397. extern char *OPFAM[];   /* Indexed mnemonic family table    */
  398. X
  399. extern struct exec HDR; /* Holds the object file's header   */
  400. X
  401. X#define LOOK_ABS 0      /* Arguments to lookup() function   */
  402. X#define LOOK_REL 1
  403. X#define LOOK_LNG 2
  404. X
  405. X#define TR_STD 0        /* Arguments to mtrans() function   */
  406. X#define TR_SEG 8
  407. X
  408. X                        /* Macro for byte input primitive   */
  409. X#define FETCH(p) \
  410. X   ++PC; p = getchar() & 0xff; objbuf[objptr++] = p
  411. X
  412. extern int close();     /* System file-close primitive      */
  413. extern int fprintf();   /* Library file-output function     */
  414. extern long lseek();    /* System file-position primitive   */
  415. extern int open();      /* System file-open primitive       */
  416. extern int printf();    /* Library output-format function   */
  417. extern int read();      /* System file-read primitive       */
  418. extern int sprintf();   /* Library string-output function   */
  419. extern char *strcat();  /* Library string-join function     */
  420. extern char *strcpy();  /* Library string-copy function     */
  421. extern int strlen();    /* Library string-length function   */
  422. X
  423. X /* * * * * * * * * * *  END OF  dis.h  * * * * * * * * * * */
  424. X
  425. X
  426. END_OF_FILE
  427. if test 7563 -ne `wc -c <'dis.h'`; then
  428.     echo shar: \"'dis.h'\" unpacked with wrong size!
  429. fi
  430. # end of 'dis.h'
  431. fi
  432. if test -f 'dis88.1' -a "${1}" != "-c" ; then 
  433.   echo shar: Will not clobber existing file \"'dis88.1'\"
  434. else
  435. echo shar: Extracting \"'dis88.1'\" \(6174 characters\)
  436. sed "s/^X//" >'dis88.1' <<'END_OF_FILE'
  437. X.TH dis88 1 LOCAL
  438. X.SH "NAME"
  439. dis88 \- 8088 symbolic disassembler
  440. X.SH "SYNOPSIS"
  441. X\fBdis88\fP [ -o ] ifile [ ofile ]
  442. X.SH "DESCRIPTION"
  443. Dis88 reads ifile, which must be in PC/IX a.out format.
  444. It interprets the binary opcodes and data locations, and
  445. writes corresponding assembler source code to stdout, or
  446. to ofile if specified.  The program's output is in the
  447. format of, and fully compatible with, the PC/IX assembler,
  448. as(1).  If a symbol table is present in ifile, labels and
  449. references will be symbolic in the output.  If the input
  450. file lacks a symbol table, the fact will be noted, and the
  451. disassembly will proceed, with the disassembler generating
  452. synthetic labels as needed.  If the input file has split
  453. I/D space, or if it is executable, the disassembler will
  454. make all necessary adjustments in address-reference calculations.
  455. X.PP
  456. If the "-o" option appears, object code will be included
  457. in comments during disassembly of the text segment.  This
  458. feature is used primarily for debugging the disassembler
  459. itself, but may provide information of passing interest
  460. to users.
  461. X.PP
  462. The program always outputs the current machine address
  463. before disassembling an opcode.  If a symbol table is
  464. present, this address is output as an assembler comment;
  465. otherwise, it is incorporated into the synthetic label
  466. which is generated internally.  Since relative jumps,
  467. especially short ones, may target unlabelled locations,
  468. the program always outputs the physical target address
  469. as a comment, to assist the user in following the code.
  470. X.PP
  471. The text segment of an object file is always padded to
  472. an even machine address.  In addition, if the file has
  473. split I/D space, the text segment will be padded to a
  474. paragraph boundary (i.e., an address divisible by 16).
  475. As a result of this padding, the disassembler may produce
  476. a few spurious, but harmless, instructions at the
  477. end of the text segment.
  478. X.PP
  479. Disassembly of the data segment is a difficult matter.
  480. The information to which initialized data refers cannot
  481. be inferred from context, except in the special case
  482. of an external data or address reference, which will be
  483. reflected in the relocation table.  Internal data and
  484. address references will already be resolved in the object file,
  485. and cannot be recreated.  Therefore, the data
  486. segment is disassembled as a byte stream, with long
  487. stretches of null data represented by an appropriate
  488. X".zerow" pseudo-op.  This limitation notwithstanding,
  489. labels (as opposed to symbolic references) are always
  490. output at appropriate points within the data segment.
  491. X.PP
  492. If disassembly of the data segment is difficult, disassembly of the
  493. bss segment is quite easy, because uninitialized data is all
  494. zero by definition.  No data
  495. is output in the bss segment, but symbolic labels are
  496. output as appropriate.
  497. X.PP
  498. XFor each opcode which takes an operand, a particular
  499. symbol type (text, data, or bss) is appropriate.  This
  500. tidy correspondence is complicated somewhat, however,
  501. by the existence of assembler symbolic constants and
  502. segment override opcodes.  Therefore, the disassembler's
  503. symbol lookup routine attempts to apply a certain amount
  504. of intelligence when it is asked to find a symbol.  If
  505. it cannot match on a symbol of the preferred type, it
  506. may return a symbol of some other type, depending on
  507. preassigned (and somewhat arbitrary) rankings within
  508. each type.  Finally, if all else fails, it returns a
  509. string containing the address sought as a hex constant;
  510. this behavior allows calling routines to use the output
  511. of the lookup function regardless of the success of its
  512. search.
  513. X.PP
  514. It is worth noting, at this point, that the symbol lookup
  515. routine operates linearly, and has not been optimized in
  516. any way.  Execution time is thus likely to increase
  517. geometrically with input file size.  The disassembler is
  518. internally limited to 1500 symbol table entries and 1500
  519. relocation table entries; while these limits are generous
  520. X(/unix, itself, has fewer than 800 symbols), they are not
  521. guaranteed to be adequate in all cases.  If the symbol
  522. table or the relocation table overflows, the disassembly
  523. aborts.
  524. X.PP
  525. XFinally, users should be aware of a bug in the assembler,
  526. which causes it not to parse the "esc" mnemonic, even
  527. though "esc" is a completely legitimate opcode which is
  528. documented in all the Intel literature.  To accommodate
  529. this deficiency, the disassembler translates opcodes of
  530. the "esc" family to .byte directives, but notes the
  531. correct mnemonic in a comment for reference.
  532. X.PP
  533. In all cases, it should be possible to submit the output
  534. of the disassembler program to the assembler, and assemble
  535. it without error.  In most cases, the resulting object
  536. code will be identical to the original; in any event, it
  537. will be functionally equivalent.
  538. X.SH "SEE ALSO"
  539. adb(1), as(1), cc(1), ld(1).
  540. X.br
  541. X"Assembler Reference Manual" in the PC/IX Programmer's
  542. Guide.
  543. X.SH "DIAGNOSTICS"
  544. X"can't access input file" if the input file cannot be
  545. found, opened, or read.
  546. X.sp
  547. X"can't open output file" if the output file cannot be
  548. created.
  549. X.sp
  550. X"warning: host/cpu clash" if the program is run on a
  551. machine with a different CPU.
  552. X.sp
  553. X"input file not in object format" if the magic number
  554. does not correspond to that of a PC/IX object file.
  555. X.sp
  556. X"not an 8086/8088 object file" if the CPU ID of the
  557. file header is incorrect.
  558. X.sp
  559. X"reloc table overflow" if there are more than 1500
  560. entries in the relocation table.
  561. X.sp
  562. X"symbol table overflow" if there are more than 1500
  563. entries in the symbol table.
  564. X.sp
  565. X"lseek error" if the input file is corrupted (should
  566. never happen).
  567. X.sp
  568. X"warning: no symbols" if the symbol table is missing.
  569. X.sp
  570. X"can't reopen input file" if the input file is removed
  571. or altered during program execution (should never happen).
  572. X.SH "BUGS"
  573. Numeric co-processor (i.e., 8087) mnemonics are not currently supported.
  574. Instructions for the co-processor are
  575. disassembled as CPU escape sequences, or as interrupts,
  576. depending on how they were assembled in the first place.
  577. X.sp
  578. Despite the program's best efforts, a symbol retrieved
  579. from the symbol table may sometimes be different from
  580. the symbol used in the original assembly.
  581. X.sp
  582. The disassembler's internal tables are of fixed size,
  583. and the program aborts if they overflow.
  584. END_OF_FILE
  585. if test 6174 -ne `wc -c <'dis88.1'`; then
  586.     echo shar: \"'dis88.1'\" unpacked with wrong size!
  587. fi
  588. # end of 'dis88.1'
  589. fi
  590. if test -f 'disfp.c' -a "${1}" != "-c" ; then 
  591.   echo shar: Will not clobber existing file \"'disfp.c'\"
  592. else
  593. echo shar: Extracting \"'disfp.c'\" \(5589 characters\)
  594. sed "s/^X//" >'disfp.c' <<'END_OF_FILE'
  595. static char *sccsid =
  596. X   "@(#) disfp.c, Ver. 2.1 created 00:00:00 87/09/01";
  597. X
  598. X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  599. X  *                                                         *
  600. X  *  Copyright (C) 1987 G. M. Harding, all rights reserved  *
  601. X  *                                                         *
  602. X  * Permission to copy and  redistribute is hereby granted, *
  603. X  * provided full source code,  with all copyright notices, *
  604. X  * accompanies any redistribution.                         *
  605. X  *                                                         *
  606. X  * This file contains handler routines for the numeric op- *
  607. X  * codes of the 8087 co-processor,  as well as a few other *
  608. X  * opcodes which are related to 8087 emulation.            *
  609. X  *                                                         *
  610. X  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  611. X
  612. X#include "dis.h"              /* Disassembler declarations  */
  613. X
  614. X#define FPINT0 0xd8           /* Floating-point interrupts  */
  615. X#define FPINT1 0xd9
  616. X#define FPINT2 0xda
  617. X#define FPINT3 0xdb
  618. X#define FPINT4 0xdc
  619. X#define FPINT5 0xdd
  620. X#define FPINT6 0xde
  621. X#define FPINT7 0xdf
  622. X
  623. X                              /* Test for floating opcodes  */
  624. X#define ISFLOP(x) \
  625. X   (((x) >= FPINT0) && ((x) <= FPINT7))
  626. X
  627. X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  628. X  *                                                         *
  629. X  * This is the  handler for the escape  family of opcodes. *
  630. X  * These opcodes place the contents of a specified  memory *
  631. X  * location on the system bus,  for access by a peripheral *
  632. X  * or by a co-processor such as the 8087. (The 8087 NDP is *
  633. X  * accessed  only  via bus  escapes.)  Due to a bug in the *
  634. X  * PC/IX assembler,  the "esc" mnemonic is not recognized; *
  635. X  * consequently,  escape opcodes are disassembled as .byte *
  636. X  * directives,  with the appropriate  mnemonic and operand *
  637. X  * included as a comment.  FOR NOW, those escape sequences *
  638. X  * corresponding  to 8087  opcodes  are  treated as simple *
  639. X  * escapes.                                                *
  640. X  *                                                         *
  641. X  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  642. X
  643. void
  644. eshand(j)
  645. X
  646. X   register int j;            /* Pointer to optab[] entry   */
  647. X
  648. X{/* * * * * * * * * *  START OF eshand()  * * * * * * * * * */
  649. X
  650. X   register char *a;
  651. X   register int k;
  652. X
  653. X   objini(j);
  654. X
  655. X   FETCH(k);
  656. X
  657. X   a = mtrans((j & 0xfd),(k & 0xc7),TR_STD);
  658. X
  659. X   mtrunc(a);
  660. X
  661. X   printf("\t.byte\t0x%02.2x\t\t| esc\t%s\n",j,a);
  662. X
  663. X   for (k = 1; k < objptr; ++k)
  664. X      printf("\t.byte\t0x%02.2x\n",objbuf[k]);
  665. X
  666. X}/* * * * * * * * * * * END OF eshand() * * * * * * * * * * */
  667. X
  668. X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  669. X  *                                                         *
  670. X  * This is the handler routine for floating-point opcodes. *
  671. X  * Since PC/IX must  accommodate  systems with and without *
  672. X  * 8087 co-processors, it allows floating-point operations *
  673. X  * to be  initiated  in either of two ways:  by a software *
  674. X  * interrput whose type is in the range 0xd8 through 0xdf, *
  675. X  * or by a CPU escape sequence, which is invoked by an op- *
  676. X  * code in the same range.  In either case, the subsequent *
  677. X  * byte determines the actual numeric operation to be per- *
  678. X  * formed.  However,  depending  on the  method of access, *
  679. X  * either  one or two code bytes will  precede  that byte, *
  680. X  * and the fphand()  routine has no way of knowing whether *
  681. X  * it was invoked by  interrupt or by an escape  sequence. *
  682. X  * Therefore, unlike all of the other handler routines ex- *
  683. X  * cept dfhand(),  fphand() does not initialize the object *
  684. X  * buffer, leaving that chore to the caller.               *
  685. X  *                                                         *
  686. X  * FOR NOW,  fphand()  does not disassemble floating-point *
  687. X  * opcodes to floating  mnemonics,  but simply outputs the *
  688. X  * object code as .byte directives.                        *
  689. X  *                                                         *
  690. X  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  691. X
  692. void
  693. fphand(j)
  694. X
  695. X   register int j;            /* Pointer to optab[] entry   */
  696. X
  697. X{/* * * * * * * * * *  START OF fphand()  * * * * * * * * * */
  698. X
  699. X   register int k;
  700. X
  701. X   segflg = 0;
  702. X
  703. X   FETCH(k);
  704. X
  705. X   printf("\t.byte\t0x%02.2x\t\t| 8087 code sequence\n",
  706. X    objbuf[0]);
  707. X
  708. X   for (k = 1; k < objptr; ++k)
  709. X      printf("\t.byte\t0x%02.2x\n",objbuf[k]);
  710. X
  711. X/* objout();                                       FOR NOW  */
  712. X
  713. X}/* * * * * * * * * * * END OF fphand() * * * * * * * * * * */
  714. X
  715. X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  716. X  *                                                         *
  717. X  * This is the  handler for  variable  software  interrupt *
  718. X  * opcodes.  It is included in this file because PC/IX im- *
  719. X  * plements its software floating-point emulation by means *
  720. X  * of interrupts.  Any interrupt in the range 0xd8 through *
  721. X  * 0xdf is an  NDP-emulation  interrupt,  and is specially *
  722. X  * handled by the assembler.                               *
  723. X  *                                                         *
  724. X  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  725. X
  726. void
  727. inhand(j)
  728. X
  729. X   register int j;            /* Pointer to optab[] entry   */
  730. X
  731. X{/* * * * * * * * * *  START OF inhand()  * * * * * * * * * */
  732. X
  733. X   register int k;
  734. X
  735. X   objini(j);
  736. X
  737. X   FETCH(k);
  738. X
  739. X   if (ISFLOP(k))
  740. X      {
  741. X      fphand(k);
  742. X      return;
  743. X      }
  744. X
  745. X   printf("%s\t%d\n",optab[j].text,k);
  746. X
  747. X   objout();
  748. X
  749. X}/* * * * * * * * * * * END OF inhand() * * * * * * * * * * */
  750. X
  751. X
  752. END_OF_FILE
  753. if test 5589 -ne `wc -c <'disfp.c'`; then
  754.     echo shar: \"'disfp.c'\" unpacked with wrong size!
  755. fi
  756. # end of 'disfp.c'
  757. fi
  758. if test -f 'dismain.c' -a "${1}" != "-c" ; then 
  759.   echo shar: Will not clobber existing file \"'dismain.c'\"
  760. else
  761. echo shar: Extracting \"'dismain.c'\" \(17384 characters\)
  762. sed "s/^X//" >'dismain.c' <<'END_OF_FILE'
  763. static char *sccsid =
  764. X   "@(#) dismain.c, Ver. 2.1 created 00:00:00 87/09/01";
  765. X
  766. X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  767. X  *                                                         *
  768. X  *  Copyright (C) 1987 G. M. Harding, all rights reserved  *
  769. X  *                                                         *
  770. X  * Permission to copy and  redistribute is hereby granted, *
  771. X  * provided full source code,  with all copyright notices, *
  772. X  * accompanies any redistribution.                         *
  773. X  *                                                         *
  774. X  * This file  contains  the source  code for the  machine- *
  775. X  * independent  portions of a disassembler  program to run *
  776. X  * in a Unix (System III) environment.  It expects, as its *
  777. X  * input, a file in standard a.out format, optionally con- *
  778. X  * taining symbol table information.  If a symbol table is *
  779. X  * present, it will be used in the disassembly; otherwise, *
  780. X  * all address references will be literal (absolute).      *
  781. X  *                                                         *
  782. X  * The disassembler  program was originally written for an *
  783. X  * Intel 8088 CPU.  However, all details of the actual CPU *
  784. X  * architecture are hidden in three machine-specific files *
  785. X  * named  distabs.c,  dishand.c,  and disfp.c  (the latter *
  786. X  * file is specific to the 8087 numeric co-processor). The *
  787. X  * code in this file is generic,  and should require mini- *
  788. X  * mal revision if a different CPU is to be targeted. If a *
  789. X  * different version of Unix is to be targeted, changes to *
  790. X  * this file may be necessary, and if a completely differ- *
  791. X  * ent OS is to be targeted, all bets are off.             *
  792. X  *                                                         *
  793. X  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  794. X
  795. X#include "dis.h"              /* Disassembler declarations  */
  796. X
  797. extern char *release;         /* Contains release string    */
  798. X
  799. static char *IFILE = NULL;    /* Points to input file name  */
  800. X
  801. static char *OFILE = NULL;    /* Points to output file name */
  802. X
  803. static char *PRG;             /* Name of invoking program   */
  804. X
  805. static unsigned long zcount;  /* Consecutive "0" byte count */
  806. X
  807. int objflg = 0;               /* Flag: output object bytes  */
  808. X
  809. X#if unix && i8086 && ibmpc    /* Set the CPU identifier     */
  810. static int cpuid = 1;
  811. X#else
  812. static int cpuid = 0;
  813. X#endif
  814. X
  815. X /* * * * * * * MISCELLANEOUS UTILITY FUNCTIONS * * * * * * */
  816. X
  817. static void
  818. usage(s)
  819. X   register char *s;
  820. X{
  821. X   fprintf(stderr,"\07usage: %s [-o] ifile [ofile]\n",s);
  822. X   exit(-1);
  823. X}
  824. X
  825. static void
  826. fatal(s,t)
  827. X   register char *s, *t;
  828. X{
  829. X   fprintf(stderr,"\07%s: %s\n",s,t);
  830. X   exit(-1);
  831. X}
  832. X
  833. static void
  834. zdump(beg)
  835. X   unsigned long beg;
  836. X{
  837. X   beg = PC - beg;
  838. X   if (beg > 1L)
  839. X      printf("\t.zerow\t%ld\n",(beg >> 1));
  840. X   if (beg & 1L)
  841. X      printf("\t.byte\t0\n");
  842. X}
  843. X
  844. static char *
  845. invoker(s)
  846. X   register char *s;
  847. X{
  848. X   extern int strlen();
  849. X   register int k;
  850. X
  851. X   k = strlen(s);
  852. X
  853. X   while (k--)
  854. X      if (s[k] == '/')
  855. X         {
  856. X         s += k;
  857. X         ++s;
  858. X         break;
  859. X         }
  860. X
  861. X   return (s);
  862. X}
  863. X
  864. X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  865. X  *                                                         *
  866. X  * This rather tricky routine supports the disdata() func- *
  867. X  * tion.  Its job is to output the code for a sequence  of *
  868. X  * data bytes whenever the object buffer is full,  or when *
  869. X  * a symbolic label is to be output. However, it must also *
  870. X  * keep track of  consecutive  zero words so that  lengthy *
  871. X  * stretches of null data can be  compressed by the use of *
  872. X  * an  appropriate  assembler  pseudo-op.  It does this by *
  873. X  * setting and testing a file-wide  flag which counts suc- *
  874. X  * cessive full buffers of null data. The function returns *
  875. X  * a logical  TRUE value if it outputs  anything,  logical *
  876. X  * FALSE otherwise.  (This enables disdata()  to determine *
  877. X  * whether to output a new  synthetic  label when there is *
  878. X  * no symbol table.)                                       *
  879. X  *                                                         *
  880. X  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  881. X
  882. static int
  883. objdump(c)
  884. X
  885. X   register char *c;
  886. X
  887. X{/* * * * * * * * * * START OF  objdump() * * * * * * * * * */
  888. X
  889. X   register int k;
  890. X   int retval = 0;
  891. X
  892. X   if (objptr == OBJMAX)
  893. X      {
  894. X      for (k = 0; k < OBJMAX; ++k)
  895. X         if (objbuf[k])
  896. X            break;
  897. X      if (k == OBJMAX)
  898. X         {
  899. X         zcount += k;
  900. X         objptr = 0;
  901. X         if (c == NULL)
  902. X            return (retval);
  903. X         }
  904. X      }
  905. X
  906. X   if (zcount)
  907. X      {
  908. X      printf("\t.zerow\t%ld\n",(zcount >> 1));
  909. X      ++retval;
  910. X      zcount = 0L;
  911. X      }
  912. X
  913. X   if (objptr)
  914. X      {
  915. X      printf("\t.byte\t");
  916. X      ++retval;
  917. X      }
  918. X   else
  919. X      return (retval);
  920. X
  921. X   for (k = 0; k < objptr; ++k)
  922. X      {
  923. X      printf("0x%02.2x",objbuf[k]);
  924. X      if (k < (objptr - 1))
  925. X         putchar(',');
  926. X      else
  927. X         putchar('\n');
  928. X      }
  929. X
  930. X   objptr = 0;
  931. X
  932. X   return (retval);
  933. X
  934. X}/* * * * * * * * * *  END OF  objdump()  * * * * * * * * * */
  935. X
  936. X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  937. X  *                                                         *
  938. X  * This  routine,  called  at the  beginning  of the input *
  939. X  * cycle for each object byte,  and before any interpreta- *
  940. X  * tion is  attempted,  searches  the symbol table for any *
  941. X  * symbolic  name with a value  corresponding  to the cur- *
  942. X  * rent PC and a type  corresponding  to the segment  type *
  943. X  * (i.e.,  text, data, or bss) specified by the function's *
  944. X  * argument. If any such name is found, a pointer to it is *
  945. X  * returned; otherwise, a NULL pointer is returned.        *
  946. X  *                                                         *
  947. X  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  948. X
  949. static char *
  950. getlab(type)
  951. X
  952. X   register int type;
  953. X
  954. X{/* * * * * * * * * *  START OF getlab()  * * * * * * * * * */
  955. X
  956. X   register int k;
  957. X   static char b[32], c[10];
  958. X
  959. X   if (symptr < 0)
  960. X      if ((type == N_TEXT)
  961. X       || ((type == N_DATA) && ( ! objptr ) && ( ! zcount )))
  962. X         {
  963. X         if (type == N_TEXT)
  964. X            sprintf(b,"T%05.5lx:",PC);
  965. X         else
  966. X            sprintf(b,"D%05.5lx:",PC);
  967. X         return (b);
  968. X         }
  969. X      else
  970. X         return (NULL);
  971. X
  972. X   for (k = 0; k <= symptr; ++k)
  973. X      if ((symtab[k].n_value == PC)
  974. X       && ((symtab[k].n_sclass & N_SECT) == type))
  975. X         {
  976. X         sprintf(b,"%s:\n",getnam(k));
  977. X         if (objflg && (type != N_TEXT))
  978. X            sprintf(c,"| %05.5lx\n",PC);
  979. X         strcat(b,c);
  980. X         return (b);
  981. X         }
  982. X
  983. X   return (NULL);
  984. X
  985. X}/* * * * * * * * * * * END OF getlab() * * * * * * * * * * */
  986. X
  987. X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  988. X  *                                                         *
  989. X  * This routine  performs a preliminary scan of the symbol *
  990. X  * table,  before disassembly begins, and outputs declara- *
  991. X  * tions of globals and constants.                         *
  992. X  *                                                         *
  993. X  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  994. X
  995. static void
  996. prolog()
  997. X
  998. X{/* * * * * * * * * *  START OF prolog()  * * * * * * * * * */
  999. X
  1000. X   register int j, flag;
  1001. X
  1002. X   if (symptr < 0)
  1003. X      return;
  1004. X
  1005. X   for (j = flag = 0; j <= symptr; ++j)
  1006. X      if ((symtab[j].n_sclass & N_CLASS) == C_EXT)
  1007. X         if (((symtab[j].n_sclass & N_SECT) > N_UNDF)
  1008. X          && ((symtab[j].n_sclass & N_SECT) < N_COMM))
  1009. X            {
  1010. X            char *c = getnam(j);
  1011. X            printf("\t.globl\t%s",c);
  1012. X            if (++flag == 1)
  1013. X               {
  1014. X               putchar('\t');
  1015. X               if (strlen(c) < 8)
  1016. X                  putchar('\t');
  1017. X               printf("| Internal global\n");
  1018. X               }
  1019. X            else
  1020. X               putchar('\n');
  1021. X            }
  1022. X         else
  1023. X            if (symtab[j].n_value)
  1024. X               {
  1025. X               char *c = getnam(j);
  1026. X               printf("\t.comm\t%s,0x%08.8lx",c,
  1027. X                symtab[j].n_value);
  1028. X               if (++flag == 1)
  1029. X                  printf("\t| Internal global\n");
  1030. X               else
  1031. X                  putchar('\n');
  1032. X               }
  1033. X
  1034. X   if (flag)
  1035. X      putchar('\n');
  1036. X
  1037. X   for (j = flag = 0; j <= relptr; ++j)
  1038. X      if (relo[j].r_symndx < S_BSS)
  1039. X         {
  1040. X         char *c = getnam(relo[j].r_symndx);
  1041. X         ++flag;
  1042. X         printf("\t.globl\t%s",c);
  1043. X         putchar('\t');
  1044. X         if (strlen(c) < 8)
  1045. X            putchar('\t');
  1046. X         printf("| Undef: %05.5lx\n",relo[j].r_vaddr);
  1047. X         }
  1048. X
  1049. X   if (flag)
  1050. X      putchar('\n');
  1051. X
  1052. X   for (j = flag = 0; j <= symptr; ++j)
  1053. X      if ((symtab[j].n_sclass & N_SECT) == N_ABS)
  1054. X         {
  1055. X         char *c = getnam(j);
  1056. X         printf("%s=0x%08.8lx",c,symtab[j].n_value);
  1057. X         if (++flag == 1)
  1058. X            {
  1059. X            printf("\t\t");
  1060. X            if (strlen(c) < 5)
  1061. X               putchar('\t');
  1062. X            printf("| Literal\n");
  1063. X            }
  1064. X         else
  1065. X            putchar('\n');
  1066. X         }
  1067. X
  1068. X   if (flag)
  1069. X      putchar('\n');
  1070. X
  1071. X}/* * * * * * * * * * * END OF prolog() * * * * * * * * * * */
  1072. X
  1073. X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1074. X  *                                                         *
  1075. X  * This function is  responsible  for  disassembly  of the *
  1076. X  * object file's text segment.                             *
  1077. X  *                                                         *
  1078. X  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1079. X
  1080. static void
  1081. distext()
  1082. X
  1083. X{/* * * * * * * * * * START OF  distext() * * * * * * * * * */
  1084. X
  1085. X   char *c;
  1086. X   register int j;
  1087. X   register void (*f)();
  1088. X
  1089. X   for (j = 0; j < (int)(HDR.a_hdrlen); ++j)
  1090. X      getchar();
  1091. X
  1092. X   printf("| %s, %s\n\n",PRG,release);
  1093. X
  1094. X   printf("| @(");
  1095. X
  1096. X   printf("#)\tDisassembly of %s",IFILE);
  1097. X
  1098. X   if (symptr < 0)
  1099. X      printf(" (no symbols)\n\n");
  1100. X   else
  1101. X      printf("\n\n");
  1102. X
  1103. X   if (HDR.a_flags & A_EXEC)
  1104. X      printf("| File is executable\n\n");
  1105. X
  1106. X   if (HDR.a_flags & A_SEP)
  1107. X      {
  1108. X      printf("| File has split I/D space, and may have\n");
  1109. X      printf("| extraneous instructions in text segment\n\n");
  1110. X      }
  1111. X
  1112. X   prolog();
  1113. X
  1114. X   printf("\t.text\t\t\t| loc = %05.5lx, size = %05.5lx\n\n",
  1115. X    PC,HDR.a_text);
  1116. X
  1117. X   segflg = 0;
  1118. X
  1119. X   for (PC = 0L; PC < HDR.a_text; ++PC)
  1120. X      {
  1121. X      j = getchar() & 0xff;
  1122. X      if ((j == 0) && ((PC + 1L) == HDR.a_text))
  1123. X         {
  1124. X         ++PC;
  1125. X         break;
  1126. X         }
  1127. X      if ((c = getlab(N_TEXT)) != NULL)
  1128. X         printf("%s",c);
  1129. X      f = optab[j].func;
  1130. X      (*f)(j);
  1131. X      }
  1132. X
  1133. X}/* * * * * * * * * *  END OF  distext()  * * * * * * * * * */
  1134. X
  1135. X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1136. X  *                                                         *
  1137. X  * This  function  handles the object file's data segment. *
  1138. X  * There is no good way to disassemble a data segment, be- *
  1139. X  * cause it is  impossible  to tell,  from the object code *
  1140. X  * alone,  what each data byte refers to.  If it refers to *
  1141. X  * an external symbol,  the reference can be resolved from *
  1142. X  * the relocation table, if there is one.  However,  if it *
  1143. X  * refers to a static symbol,  it cannot be  distinguished *
  1144. X  * from numeric, character, or other pointer data. In some *
  1145. X  * cases,  one might make a semi-educated  guess as to the *
  1146. X  * nature of the data,  but such  guesses  are  inherently *
  1147. X  * haphazard,  and they are  bound to be wrong a good por- *
  1148. X  * tion of the time.  Consequently,  the data  segment  is *
  1149. X  * disassembled  as a byte  stream,  which will satisfy no *
  1150. X  * one but which, at least, will never mislead anyone.     *
  1151. X  *                                                         *
  1152. X  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1153. X
  1154. static void
  1155. disdata()
  1156. X
  1157. X{/* * * * * * * * * * START OF  disdata() * * * * * * * * * */
  1158. X
  1159. X   register char *c;
  1160. X   register int j;
  1161. X   unsigned long end;
  1162. X
  1163. X   putchar('\n');
  1164. X
  1165. X   if (HDR.a_flags & A_SEP)
  1166. X      {
  1167. X      PC = 0L;
  1168. X      end = HDR.a_data;
  1169. X      }
  1170. X   else
  1171. X      end = HDR.a_text + HDR.a_data;
  1172. X
  1173. X   printf("\t.data\t\t\t| loc = %05.5lx, size = %05.5lx\n\n",
  1174. X    PC,HDR.a_data);
  1175. X
  1176. X   segflg = 0;
  1177. X
  1178. X   for (objptr = 0, zcount = 0L; PC < end; ++PC)
  1179. X      {
  1180. X      if ((c = getlab(N_DATA)) != NULL)
  1181. X         {
  1182. X         objdump(c);
  1183. X         printf("%s",c);
  1184. X         }
  1185. X      if (objptr >= OBJMAX)
  1186. X         if (objdump(NULL) && (symptr < 0))
  1187. X            printf("D%05.5lx:",PC);
  1188. X      j = getchar() & 0xff;
  1189. X      objbuf[objptr++] = j;
  1190. X      }
  1191. X
  1192. X   objdump("");
  1193. X
  1194. X}/* * * * * * * * * *  END OF  disdata()  * * * * * * * * * */
  1195. X
  1196. X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1197. X  *                                                         *
  1198. X  * This  function  handles the object  file's bss segment. *
  1199. X  * Disassembly of the bss segment is easy,  because every- *
  1200. X  * thing in it is zero by definition.                      *
  1201. X  *                                                         *
  1202. X  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1203. X
  1204. static void
  1205. disbss()
  1206. X
  1207. X{/* * * * * * * * * *  START OF disbss()  * * * * * * * * * */
  1208. X
  1209. X   register int j;
  1210. X   register char *c;
  1211. X   unsigned long beg, end;
  1212. X
  1213. X   putchar('\n');
  1214. X
  1215. X   if (HDR.a_flags & A_SEP)
  1216. X      end = HDR.a_data + HDR.a_bss;
  1217. X   else
  1218. X      end = HDR.a_text + HDR.a_data + HDR.a_bss;
  1219. X
  1220. X   printf("\t.bss\t\t\t| loc = %05.5lx, size = %05.5lx\n\n",
  1221. X    PC,HDR.a_bss);
  1222. X
  1223. X   segflg = 0;
  1224. X
  1225. X   for (beg = PC; PC < end; ++PC)
  1226. X      if ((c = getlab(N_BSS)) != NULL)
  1227. X         {
  1228. X         if (PC > beg)
  1229. X            {
  1230. X            zdump(beg);
  1231. X            beg = PC;
  1232. X            }
  1233. X         printf("%s",c);
  1234. X         }
  1235. X
  1236. X   if (PC > beg)
  1237. X      zdump(beg);
  1238. X
  1239. X}/* * * * * * * * * * * END OF disbss() * * * * * * * * * * */
  1240. X
  1241. X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1242. X  *                                                         *
  1243. X  * This is the program  entry  point.  The command line is *
  1244. X  * searched for an input file name, which must be present. *
  1245. X  * An optional output file name is also permitted; if none *
  1246. X  * is found, standard output is the default.  One command- *
  1247. X  * line option is available:  "-o",  which causes the pro- *
  1248. X  * gram to include  object code in comments along with its *
  1249. X  * mnemonic output.                                        *
  1250. X  *                                                         *
  1251. X  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1252. X
  1253. void
  1254. main(argc,argv)
  1255. X
  1256. X   int argc;                  /* Command-line args from OS  */
  1257. X   register char **argv;
  1258. X
  1259. X{/* * * * * * * * * * * START OF main() * * * * * * * * * * */
  1260. X
  1261. X   char a[1024];
  1262. X   register int fd;
  1263. X   long taboff, tabnum;
  1264. X   long reloff, relnum;
  1265. X
  1266. X   PRG = invoker(*argv);
  1267. X
  1268. X   while (*++argv != NULL)    /* Process command-line args  */
  1269. X      if (**argv == '-')
  1270. X         switch (*++*argv)
  1271. X            {
  1272. X            case 'o' :
  1273. X               if (*++*argv)
  1274. X                  usage(PRG);
  1275. X               else
  1276. X                  ++objflg;
  1277. X               break;
  1278. X            default :
  1279. X               usage(PRG);
  1280. X            }
  1281. X      else
  1282. X         if (IFILE == NULL)
  1283. X            IFILE = *argv;
  1284. X         else if (OFILE == NULL)
  1285. X            OFILE = *argv;
  1286. X         else
  1287. X            usage(PRG);
  1288. X
  1289. X   if (IFILE == NULL)
  1290. X      usage(PRG);
  1291. X   else
  1292. X      if ((fd = open(IFILE,O_RDONLY)) < 0)
  1293. X         {
  1294. X         sprintf(a,"can't access input file %s",IFILE);
  1295. X         fatal(PRG,a);
  1296. X         }
  1297. X
  1298. X   if (OFILE != NULL)
  1299. X      if (freopen(OFILE,"w",stdout) == NULL)
  1300. X         {
  1301. X         sprintf(a,"can't open output file %s",OFILE);
  1302. X         fatal(PRG,a);
  1303. X         }
  1304. X
  1305. X   if ( ! cpuid )
  1306. X      fprintf(stderr,"\07%s: warning: host/cpu clash\n",PRG);
  1307. X
  1308. X   read(fd,&HDR,sizeof(struct exec));
  1309. X
  1310. X   if (BADMAG(HDR))
  1311. X      {
  1312. X      sprintf(a,"input file %s not in object format",IFILE);
  1313. X      fatal(PRG,a);
  1314. X      }
  1315. X
  1316. X   if (HDR.a_cpu != A_I8086)
  1317. X      {
  1318. X      sprintf(a,"%s is not an 8086/8088 object file",IFILE);
  1319. X      fatal(PRG,a);
  1320. X      }
  1321. X
  1322. X   if (HDR.a_hdrlen <= A_MINHDR)
  1323. X      HDR.a_trsize = HDR.a_drsize =
  1324. X      HDR.a_tbase = HDR.a_dbase =
  1325. X      HDR.a_lnums = HDR.a_toffs = 0L;
  1326. X
  1327. X   reloff = HDR.a_text        /* Compute reloc data offset  */
  1328. X          + HDR.a_data
  1329. X          + (long)(HDR.a_hdrlen);
  1330. X
  1331. X   relnum =
  1332. X      (HDR.a_trsize + HDR.a_drsize) / sizeof(struct reloc);
  1333. X
  1334. X   taboff = reloff            /* Compute name table offset  */
  1335. X          + HDR.a_trsize
  1336. X          + HDR.a_drsize;
  1337. X
  1338. X   tabnum = HDR.a_syms / sizeof(struct nlist);
  1339. X
  1340. X   if (relnum > MAXSYM)
  1341. X      fatal(PRG,"reloc table overflow");
  1342. X
  1343. X   if (tabnum > MAXSYM)
  1344. X      fatal(PRG,"symbol table overflow");
  1345. X
  1346. X   if (relnum)                            /* Get reloc data */
  1347. X      if (lseek(fd,reloff,0) != reloff)
  1348. X         fatal(PRG,"lseek error");
  1349. X      else
  1350. X         {
  1351. X         for (relptr = 0; relptr < relnum; ++relptr)
  1352. X            read(fd,&relo[relptr],sizeof(struct reloc));
  1353. X         relptr--;
  1354. X         }
  1355. X
  1356. X   if (tabnum)                            /* Read in symtab */
  1357. X      if (lseek(fd,taboff,0) != taboff)
  1358. X         fatal(PRG,"lseek error");
  1359. X      else
  1360. X         {
  1361. X         for (symptr = 0; symptr < tabnum; ++symptr)
  1362. X            read(fd,&symtab[symptr],sizeof(struct nlist));
  1363. X         symptr--;
  1364. X         }
  1365. X   else
  1366. X      fprintf(stderr,"\07%s: warning: no symbols\n",PRG);
  1367. X
  1368. X   close(fd);
  1369. X
  1370. X   if (freopen(IFILE,"r",stdin) == NULL)
  1371. X      {
  1372. X      sprintf(a,"can't reopen input file %s",IFILE);
  1373. X      fatal(PRG,a);
  1374. X      }
  1375. X
  1376. X   distext();
  1377. X
  1378. X   disdata();
  1379. X
  1380. X   disbss();
  1381. X
  1382. X   exit(0);
  1383. X
  1384. X}/* * * * * * * * * * *  END OF main()  * * * * * * * * * * */
  1385. X
  1386. X
  1387. END_OF_FILE
  1388. if test 17384 -ne `wc -c <'dismain.c'`; then
  1389.     echo shar: \"'dismain.c'\" unpacked with wrong size!
  1390. fi
  1391. # end of 'dismain.c'
  1392. fi
  1393. if test -f 'disrel.c' -a "${1}" != "-c" ; then 
  1394.   echo shar: Will not clobber existing file \"'disrel.c'\"
  1395. else
  1396. echo shar: Extracting \"'disrel.c'\" \(742 characters\)
  1397. sed "s/^X//" >'disrel.c' <<'END_OF_FILE'
  1398. static char *copyright =
  1399. X   "@(#) Copyright (C) 1987 G. M. Harding, all rights reserved";
  1400. X
  1401. static char *sccsid =
  1402. X   "@(#) disrel.c, Ver. 2.1 created 00:00:00 87/09/01";
  1403. X
  1404. char *release =
  1405. X   "release 2.1 (PC/IX)";
  1406. X
  1407. X /*
  1408. X **
  1409. X ** This file documents the major revisions to the 8088 sym-
  1410. X ** bolic disassembler. It also contains the release string
  1411. X ** which is output at the head of each disassembly, and the
  1412. X ** copyright string which must be incorporated in any code
  1413. X ** distribution.
  1414. X **
  1415. X ** Permission to copy and redistribute is hereby granted,
  1416. X ** provided full source code, with all copyright notices,
  1417. X ** accompanies any redistribution.
  1418. X **
  1419. X ** REVISION HISTORY:
  1420. X **
  1421. X ** SEP 87:
  1422. X **    After internal shakeout, released on Usenet.
  1423. X **
  1424. X */
  1425. X
  1426. END_OF_FILE
  1427. if test 742 -ne `wc -c <'disrel.c'`; then
  1428.     echo shar: \"'disrel.c'\" unpacked with wrong size!
  1429. fi
  1430. # end of 'disrel.c'
  1431. fi
  1432. echo shar: End of archive 1 \(of 2\).
  1433. cp /dev/null ark1isdone
  1434. MISSING=""
  1435. for I in 1 2 ; do
  1436.     if test ! -f ark${I}isdone ; then
  1437.     MISSING="${MISSING} ${I}"
  1438.     fi
  1439. done
  1440. if test "${MISSING}" = "" ; then
  1441.     echo You have unpacked both archives.
  1442.     rm -f ark[1-9]isdone
  1443. else
  1444.     echo You still need to unpack the following archives:
  1445.     echo "        " ${MISSING}
  1446. fi
  1447. ##  End of shell archive.
  1448. exit 0
  1449.